#include <iostream>
#include <memory>
#include <string>

using namespace std;

class StrVec {
    public:
        StrVec();
        template <class... Args> void emplace_back(Args&&...);
        size_t size() const;
        size_t capacity() const;
        string* begin() const;
        string* end() const;
    private:
        static allocator<string> alloc;
        void chk_n_alloc();
        void free();                    // 销毁元素并释放内存
        void reallocate();              // 获得更多内存并拷贝已有元素
        string *elements;               // 指向数组首元素的指针
        string *first_free;             // 指向数组第一个空闲元素的指针
        string *cap;                    // 指向数组尾后位置的指针
};

// 类的静态数据成员需要在类外定义
allocator<string> StrVec::alloc;

// 很重要，不然会报错！
inline StrVec::StrVec(): elements(nullptr), first_free(nullptr), cap(nullptr) {}

template <class... Args>
inline void StrVec::emplace_back(Args&&... args)
{
    chk_n_alloc(); // 如果需要的话重新分配 StrVec 内存空间
    // forward<T1>(t1), forward<T2>(t2), ..., forward<Tn>(tn)
    alloc.construct(first_free++, forward<Args>(args)...);
}

inline size_t StrVec::size() const { return first_free - elements; }

inline size_t StrVec::capacity() const { return cap - elements; }

inline void StrVec::chk_n_alloc() { if (size() == capacity()) reallocate(); }

inline void StrVec::free()
{
    // 不能传递给 deallocate 一个空指针，如果 elements 为0，函数什么也不做
    if (elements) {
        // 逆序销毁旧元素
        for (auto p = first_free; p != elements;)
            alloc.destroy(--p);
        alloc.deallocate(elements, cap - elements);
    }
}

inline string* StrVec::begin() const { return elements; }

inline string* StrVec::end() const { return first_free; }

inline void StrVec::reallocate()
{
    auto newcapacity = size() ? 2 * size() : 1;
    auto first = alloc.allocate(newcapacity);
    // 移动迭代器
    auto last = uninitialized_copy(make_move_iterator(begin()),
                                    make_move_iterator(end()),
                                    first);
    free();
    elements = first;
    first_free = last;
    cap = elements + newcapacity;
}

void printStrVec(StrVec &svec)
{
    for (auto p = svec.begin(); p != svec.end(); ++p)
        cout << *p << " ";
    cout << endl;
}

int main()
{
    StrVec svec;
    // forward<int>(10), forward<char>('c')
    svec.emplace_back(10, 'c'); // 将 cccccccccc 添加为新的元素
    printStrVec(svec);

    // 使用 forward 来保证如果传入一个右值，则 construct 也会得到一个右值
    svec.emplace_back(string("the end"));
    printStrVec(svec);
}